package com.uziot.activiti6.service;

import com.uziot.activiti6.common.dto.*;
import com.uziot.activiti6.common.util.ProcessUtils;
import com.uziot.activiti6.service.ActivitiService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;


/**
 * @author shidt
 * @version V1.0
 * @className ActivitiServiceImpl
 * @date 2021-02-26 10:38:41
 * @description 添加了一些常用的流程管理功能，有待测试
 */

@Service
@Slf4j
public class ActivitiServiceImpl implements ActivitiService {

    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private ManagementService managementService;

    /**
     * 发布规则文件
     *
     * @param bpmnName bpmnName
     */
    @Override
    public void deploy(String bpmnName) {
        String bpmn = "processes/" + bpmnName;
        // 创建一个部署对象
        repositoryService.createDeployment()
                // 添加部署的名称
                .name(bpmnName)
                .key(bpmnName)
                .addInputStream(bpmn, this.getClass().getClassLoader().getResourceAsStream(bpmn))
                //完成部署
                .deploy();
    }

    /**
     * 发布规则文件
     *
     * @param fileName fileName
     */
    @Override
    public void deploy(InputStream fileInputStream, String fileName) {
        ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
        // 使用deploy方法发布流程
        repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .name(fileName)
                .deploy();
    }


    @Override
    public ProcessInstance startProcessInstance(String instanceKey, Map<String, Object> variables) {
        /*
         * 启动流程  并获取流程实例
         * 因为该请假单流程可以会启动多个所以每启动一个请假单流程都会在数据库中插入一条新版本的流程数据
         * 通过key启动的流程就是当前key下最新版本的流程
         */
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(instanceKey, variables);
        if (log.isInfoEnabled()) {
            log.info("启动流程成功，流程实例ID:[{}],activitiId:[{}]",
                    processInstance.getId(), processInstance.getActivityId());
        }
        return processInstance;
    }

    @Override
    public List<ProcessDefinitionDTO> processDefinitionQuery(String instanceKey) {
        //创建查询对象
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        ProcessDefinitionQuery processDefinitionQuery = query.latestVersion();
        if (StringUtils.isBlank(instanceKey) || StringUtils.isEmpty(instanceKey)) {
            processDefinitionQuery.list();
        } else {
            query.processDefinitionKey(instanceKey);
        }
        //添加查询条件
        // .processDefinitionName("My process")//通过name获取
        // .orderByProcessDefinitionId()//根据ID排序
        //执行查询获取流程定义明细
        List<ProcessDefinition> pds = query.list();
        log.debug("queryProcdef query list:" + pds);
        if (pds != null && pds.size() > 0) {
            for (ProcessDefinition pd : pds) {
                log.debug("ID:" + pd.getId() + ",NAME:" + pd.getName() + ",KEY:" + pd.getKey() + ",VERSION:" + pd.getVersion() + ",RESOURCE_NAME:" + pd.getResourceName() + ",DGRM_RESOURCE_NAME:" + pd.getDiagramResourceName());
            }
        }
        return listToBeanDto(pds, ProcessDefinitionDTO.class);
    }

    @Override
    public List<TaskDTO> queryTask(String assignee, String candidateUser,
                                   String candidateGroup, int firstResult, int maxResults) {
        // 获取任务服务对象
        // 根据接收人获取该用户的任务
        TaskQuery taskQuery = taskService.createTaskQuery();
        if (!StringUtils.isBlank(assignee)) {
            taskQuery.taskAssignee(assignee);
        }
        // 查询候选人
        if (!StringUtils.isBlank(candidateUser)) {
            taskQuery.taskCandidateUser(candidateUser);
        }
        // 查询候选组
        if (!StringUtils.isBlank(candidateGroup)) {
            taskQuery.taskCandidateGroup(candidateGroup);
        }
        List<Task> tasks = taskQuery.listPage(firstResult, maxResults);
        List<TaskDTO> taskDtoList = null;
        if (tasks != null && tasks.size() > 0) {
            taskDtoList = listToBeanDto(tasks, TaskDTO.class, "variables");
            for (TaskDTO taskDto : taskDtoList) {
                Map<String, Object> variables = taskService.getVariables(taskDto.getId());
                taskDto.setVariables(variables);
                log.debug("ID:[{}],姓名:[{}],接收人:[{}],开始时间:[{}]",
                        taskDto.getId(), taskDto.getName(), taskDto.getAssignee(), taskDto.getCreateTime());
            }
        }
        return taskDtoList;
    }

    /**
     * 查询我的待办事项
     *
     * @param processQueryInDTO processQueryInDTO
     * @return List
     */
    @Override
    public List<MyTodoOutDTO> getTodoTasks(ProcessQueryInDTO processQueryInDTO) {
        TaskQuery taskQuery = taskService.createTaskQuery();

        if (StringUtils.isNotBlank(processQueryInDTO.getUsername())) {
            taskQuery.taskCandidateOrAssigned(processQueryInDTO.getUsername());
        }
        if (StringUtils.isNotBlank(processQueryInDTO.getTaskName())) {
            taskQuery.taskNameLike(ProcessUtils.jointLike(processQueryInDTO.getTaskName()));
        }
        if (StringUtils.isNotBlank(processQueryInDTO.getProcessName())) {
            taskQuery.processDefinitionNameLike(ProcessUtils.jointLike(processQueryInDTO.getProcessName()));
        }

        taskQuery.orderByTaskCreateTime().desc();

        List<MyTodoOutDTO> myTodos = new ArrayList<>();
        List<Task> tasks = taskQuery.listPage(processQueryInDTO.getPageNum(), processQueryInDTO.getPageSize());
        tasks.forEach(task -> {
            MyTodoOutDTO myTodoOutDTO = new MyTodoOutDTO();
            BeanUtils.copyProperties(task, myTodoOutDTO);
            HistoricProcessInstance historicProcessInstance
                    = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId()).singleResult();
            myTodoOutDTO.setProcessName(historicProcessInstance.getName());
            myTodoOutDTO.setStartUser(historicProcessInstance.getStartUserId());
            myTodos.add(myTodoOutDTO);
        });
        return myTodos;
    }

    /**
     * 我已经办结的事项
     *
     * @param processQueryInDTO 查询封装
     * @return 列表
     */
    @Override
    public List<MyDoneOutDTO> getDoneTasks(ProcessQueryInDTO processQueryInDTO) {
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();

        if (StringUtils.isNotBlank(processQueryInDTO.getUsername())) {
            historicTaskInstanceQuery.taskAssignee(processQueryInDTO.getUsername());
        }
        if (StringUtils.isNotBlank(processQueryInDTO.getTaskName())) {
            historicTaskInstanceQuery.taskNameLike(ProcessUtils.jointLike(processQueryInDTO.getTaskName()));
        }
        if (StringUtils.isNotBlank(processQueryInDTO.getProcessName())) {
            historicTaskInstanceQuery.processDefinitionNameLike(ProcessUtils.jointLike(processQueryInDTO.getProcessName()));
        }

        historicTaskInstanceQuery.finished().orderByHistoricTaskInstanceEndTime().desc();

        List<HistoricTaskInstance> historicTaskInstances = historicTaskInstanceQuery.listPage(processQueryInDTO.getPageNum(), processQueryInDTO.getPageSize());
        List<MyDoneOutDTO> myDoneOuts = new ArrayList<>();
        historicTaskInstances.forEach(historicTaskInstance -> {
            MyDoneOutDTO myDoneOutDTO = new MyDoneOutDTO();
            BeanUtils.copyProperties(historicTaskInstance, myDoneOutDTO);

            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();

            myDoneOutDTO.setProcessName(historicProcessInstance.getName());
            myDoneOutDTO.setStartUser(historicProcessInstance.getStartUserId());
            // TODO: 2021/3/25 审批操作
            String deleteReason = historicTaskInstance.getDeleteReason();
            if (deleteReason != null && (deleteReason.contains("驳回") || deleteReason.contains("回退"))) {
                myDoneOutDTO.setApproveAction("驳回");
            } else {
                myDoneOutDTO.setApproveAction("同意");
            }

            if (historicProcessInstance.getEndTime() == null) {
                myDoneOutDTO.setProcessStatus(ProcessUtils.FLOW_STATUS_RUNNING);
            } else {
                myDoneOutDTO.setProcessStatus(ProcessUtils.FLOW_STATUS_END);
            }
            myDoneOuts.add(myDoneOutDTO);
        });

        return myDoneOuts;
    }

    /**
     * 我的申请列表
     *
     * @param processQueryInDTO processQueryInDTO
     * @return list
     */
    @Override
    public List<MyApplyOutDTO> getApplyTasks(ProcessQueryInDTO processQueryInDTO) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        if (StringUtils.isNotBlank(processQueryInDTO.getUsername())) {
            historicProcessInstanceQuery.startedBy(processQueryInDTO.getUsername());
        }
        if (StringUtils.isNotBlank(processQueryInDTO.getProcessName())) {
            String jointLike = ProcessUtils.jointLike(processQueryInDTO.getProcessName());
            historicProcessInstanceQuery.processDefinitionName(jointLike);
        }

        historicProcessInstanceQuery.orderByProcessInstanceStartTime().desc();
        List<HistoricProcessInstance> historicProcessInstances
                = historicProcessInstanceQuery
                .listPage(processQueryInDTO.getPageNum(), processQueryInDTO.getPageSize());
        // 总条数
        long count = historicProcessInstanceQuery.count();
        List<MyApplyOutDTO> myApplyOuts = new ArrayList<>();
        historicProcessInstances.forEach(historicProcessInstance -> {
            MyApplyOutDTO myApplyOutDTO = new MyApplyOutDTO();
            BeanUtils.copyProperties(historicProcessInstance, myApplyOutDTO);

            String processInstanceId = historicProcessInstance.getId();
            StringBuilder currentTaskNames = new StringBuilder();
            StringBuilder currentTaskIds = new StringBuilder();

            // 注意这里，需要和业务数据提交的表单相互配合
            final FlowData flowData = ProcessUtils.getHisFlowData(processInstanceId);
            myApplyOutDTO.setTheme(flowData.getTheme());

            if (historicProcessInstance.getEndTime() == null) {
                // 未提交、审批中
                // 流程状态。未提交、审批中、审批通过、拒绝
                myApplyOutDTO.setProcessStatus(ProcessUtils.FLOW_STATUS_RUNNING);
                List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                        .processInstanceId(processInstanceId)
                        .unfinished().list();
                // 未提交
                if (flowData.isFirstNode()) {
                    myApplyOutDTO.setProcessStatus(ProcessUtils.FLOW_STATUS_NOT_SUBMIT);
                }
                // 获取当前处理任务节点名称
                list.forEach(taskInstance -> {
                    if (currentTaskIds.length() > 0) {
                        currentTaskIds.append(",");
                        currentTaskNames.append(",");
                    }
                    currentTaskIds.append(taskInstance.getId());
                    currentTaskNames.append(taskInstance.getName());
                });
            } else {
                // 审批通过、拒绝
                // 流程状态。未提交、审批中、审批通过、拒绝
                myApplyOutDTO.setProcessStatus(ProcessUtils.FLOW_STATUS_END);
            }

            myApplyOutDTO.setCurrentTaskNames(currentTaskNames.toString());
            myApplyOutDTO.setCurrentTaskIds(currentTaskIds.toString());
            myApplyOutDTO.setSubmitTime(flowData.getFirstSubmitTime());

            myApplyOuts.add(myApplyOutDTO);
        });
        return myApplyOuts;
    }


    @Override
    public Map<String, Object> queryVariables(String taskId) {
        return taskService.getVariables(taskId);
    }

    @Override
    public List<HistoricTaskInstanceDTO> queryTaskHistory(String processInstanceId) {
        // 创建历史任务实例查询
        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricTaskInstanceStartTime().asc()
                .list();

        List<HistoricTaskInstanceDTO> list1 = null;
        if (list != null && list.size() > 0) {
            list1 = new ArrayList<>();

            for (HistoricTaskInstance hti : list) {
                if (log.isDebugEnabled()) {
                    log.debug("历史ID:[{}],历史名[{}],历史实例ID:[{}],发起时间[{}],结束时间:[{}],流程花费时间:[{}]",
                            hti.getId(), hti.getName(), hti.getProcessInstanceId(),
                            hti.getStartTime(), hti.getEndTime(), hti.getDurationInMillis());
                }

                HistoricTaskInstanceDTO historicTaskInstanceDTO = objToBeanDto(hti, HistoricTaskInstanceDTO.class);
                if (historicTaskInstanceDTO != null) {
                    // 查询历史赋值信息
                    List<HistoricVariableInstance> list2 =
                            historyService.createHistoricVariableInstanceQuery().taskId(hti.getId()).list();

                    if (list2 != null && list2.size() > 0) {
                        Map<String, Object> variables = new HashMap<>(8);
                        for (HistoricVariableInstance historicVariableInstance : list2) {
                            // 申请附带参数
                            String variableName = historicVariableInstance.getVariableName();
                            Object value = historicVariableInstance.getValue();
                            variables.put(variableName, value);
                        }
                        historicTaskInstanceDTO.setVariables(variables);
                    }
                    list1.add(historicTaskInstanceDTO);
                }
            }
        }
        return list1;
    }

    @Override
    public List<HistoricVariableInstance> queryTaskHistoryVariables(String processInstanceId) {
        return historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(processInstanceId).list();
    }

    @Override
    public void completeTask(String taskId, String assignee,
                             Map<String, Object> variables,
                             Map<String, Object> param) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //完成请假申请任务
        taskService.setVariablesLocal(taskId, variables);
        if (!StringUtils.isBlank(assignee)) {
            taskService.setAssignee(taskId, assignee);
        }
        taskService.complete(taskId, variables);
        if (task != null) {
            param.put("isFinish", isFinishProcess(task.getProcessInstanceId()));
        }

    }

    /**
     * 任务指派
     *
     * @param taskId   taskId
     * @param assignee assignee
     */
    @Override
    public void claimTask(String taskId, String assignee) {
        taskService.claim(taskId, assignee);
    }

    @Override
    public void deleteTask(String taskId) {
        taskService.deleteTask(taskId);
    }

    @Override
    public void deleteRuntimeTask(String processInstanceId, String deleteReason) {
        runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
    }


    @Override
    public boolean isFinishProcess(String processInstanceId) {
        // 判断流程是否结束，查询正在执行的执行对象表
        ProcessInstance rpi = processEngine.getRuntimeService()
                // 创建流程实例查询对象
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        return rpi == null;
    }

    /**
     * 查询所有待办任务
     *
     * @param firstResult 开始位置
     * @param maxResults  最大记录数
     * @return 列表
     */
    @Override
    public List<TaskDTO> queryWaitTask(int firstResult, int maxResults) {
        List<Task> list = taskService.createTaskQuery().listPage(firstResult, maxResults);
        List<TaskDTO> taskDdtos = listToBeanDto(list, TaskDTO.class, "variables");
        taskDdtos.forEach(task -> {
            Map<String, Object> variables = taskService.getVariables(task.getId());
            task.setVariables(variables);
        });
        return taskDdtos;
    }


    @Override
    public void rejectTask(String taskId, String assignee, Map<String, Object> variables, boolean returnStart) {
        //当前任务
        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (currentTask == null) {
            throw new ActivitiException("根据当前任务ID：[" + taskId + "]，没有找到对应的待执行任务！");
        }

        //获取流程定义
        BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId());

        String processInstanceId = currentTask.getProcessInstanceId();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .activityType("userTask").finished()
                .orderByHistoricActivityInstanceEndTime().asc().list();
        if (list == null || list.size() == 0) {
            throw new ActivitiException("操作历史流程不存在");
        }
        // 获取目标节点定义
        FlowNode targetNode = null;
        String comment;
        // 驳回到发起点
        if (returnStart) {
            HistoricActivityInstance historicActivityInstance = list.get(0);
            String activityId = historicActivityInstance.getActivityId();
            // 找到目标节点
            targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
            comment = "驳回到起点";
        } else {
            // 驳回到上一个节点
            String taskDefinitionKey = currentTask.getTaskDefinitionKey();
            FlowNode currNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(taskDefinitionKey);
            // 倒序审核任务列表，最后一个不与当前节点相同的节点设置为目标节点
            for (int i = 0; i < list.size(); i++) {
                String activityId = list.get(i).getActivityId();
                FlowNode lastNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
                if (list.size() > 0 && currNode.getId().equals(lastNode.getId())) {
                    String activityIdOld = list.get(i - 1).getActivityId();
                    // 找到目标节点
                    targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityIdOld);
                    break;
                }
            }
            if (targetNode == null && list.size() > 0) {
                HistoricActivityInstance historicActivityInstance = list.get(list.size() - 1);
                String activityId = historicActivityInstance.getActivityId();
                // 找到目标节点
                targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
            }
            comment = "驳回上一环节";
        }
        if (targetNode == null) {
            throw new ActivitiException("开始节点不存在");
        }
        ProcessUtils.nodeJumpTo(taskId, targetNode.getId(), variables, comment);
    }

    @Override
    public void suspendProcessInstance(String processInstanceId) {
        runtimeService.suspendProcessInstanceById(processInstanceId);
    }

    @Override
    public void activateProcessInstance(String processInstanceId) {
        runtimeService.activateProcessInstanceById(processInstanceId);
    }

    @Override
    public void suspendProcessDefinitionByIds(List<String> deploymentIds) {
        deploymentIds.forEach(deploymentId -> {
            ProcessDefinition processDefinition = ProcessUtils.getProcessDefinition(deploymentId);
            if (!processDefinition.isSuspended()) {
                repositoryService.suspendProcessDefinitionById(processDefinition.getId());
            }
        });
    }

    @Override
    public void activateProcessDefinitionByIds(List<String> deploymentIds) {
        deploymentIds.forEach(deploymentId -> {
            ProcessDefinition processDefinition = ProcessUtils.getProcessDefinition(deploymentId);
            if (processDefinition.isSuspended()) {
                repositoryService.activateProcessDefinitionById(processDefinition.getId());
            }
        });
    }

    /**
     * 撤回审批的任务
     *
     * @param oldTaskId   已审批的任务ID
     * @param currentUser 当前用户
     */
    @Override
    public void withdrawApproval(String oldTaskId, String currentUser) {
        HistoricTaskInstance historicTaskInstance = ProcessUtils.getHistoricTaskInstance(oldTaskId);
        // 目标跳转节点
        final String targetNodeId = historicTaskInstance.getTaskDefinitionKey();
        final String processDefinitionId = historicTaskInstance.getProcessDefinitionId();
        final String processInstanceId = historicTaskInstance.getProcessInstanceId();

        if (ProcessUtils.isFinished(processInstanceId)) {
            throw new ActivitiException("流程已结束，不能撤回");
        }

        // 判断节点是否已被提交，如已提交则不能撤回
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        if (tasks.size() == 1) {
            Task currentTask = tasks.get(0);
            String currentTaskId = currentTask.getId();
            String currentNodeId = currentTask.getTaskDefinitionKey();

            final Map<String, Object> variables = taskService.getVariables(currentTaskId);

            // 计算期望节点ID
            List<UserTask> nextNodes = ProcessUtils.getNextNode(processDefinitionId, targetNodeId, variables);
            if (nextNodes.size() > 1) {
                throw new ActivitiException("撤回失败，任务已被提交");
            }
            UserTask userTask = nextNodes.get(0);
            String expectNodeId = userTask.getId();
            if (currentNodeId.equals(expectNodeId)) {
                // 撤回
               // ProcessUtils.setNextUser(currentUser, variables);
                ProcessUtils.nodeJumpTo(currentTaskId, targetNodeId, variables, "撤回");
            } else {
                throw new ActivitiException("撤回失败，任务已被提交");
            }

        } else if (tasks.size() > 1) {
            // TODO: 2020/5/1 多任务节点撤回
            throw new ActivitiException("目前暂不支持多任务撤回");
        } else {
            throw new ActivitiException("撤回失败，任务已被提交或不存在");
        }

    }

    @Override
    public List<CommentOutDTO> getProcessInstanceComments(String processInstanceId) {
        List<Comment> comments = taskService.getProcessInstanceComments(processInstanceId, "comment");
        ArrayList<CommentOutDTO> commentOuts = new ArrayList<>();
        for (int i = comments.size() - 1; i >= 0; i--) {
            CommentOutDTO commentOutDTO = new CommentOutDTO();
            Comment comment = comments.get(i);
            BeanUtils.copyProperties(comment, commentOutDTO);
            HistoricTaskInstance historicTaskInstance = ProcessUtils.getHistoricTaskInstance(comment.getTaskId());
            commentOutDTO.setUsername(historicTaskInstance.getAssignee());
            commentOutDTO.setTaskName(historicTaskInstance.getName());
            commentOuts.add(commentOutDTO);
        }
        return commentOuts;
    }


    /***
     * 转化显示Bean
     * @param list 待转化列表
     * @param clazz 显示类
     * @param <T> 泛型
     * @return list
     */
    private <T> List<T> listToBeanDto(List<?> list, Class<T> clazz, String... ignoreProperties) {
        if (list == null) {
            return null;
        }
        List<T> rlist = new ArrayList<>();
        try {
            for (Object obj : list) {
                T t = objToBeanDto(obj, clazz, ignoreProperties);
                rlist.add(t);
            }
        } catch (Exception e) {
            log.error("listToBeanVo error:" + e.getMessage());
            e.printStackTrace();
        }
        return rlist;
    }

    /**
     * 复制源对象属性到目标对象
     *
     * @param obj              obj
     * @param clazz            clazz
     * @param ignoreProperties ignoreProperties
     * @param <T>              t
     * @return t
     */
    private <T> T objToBeanDto(Object obj, Class<T> clazz, String... ignoreProperties) {
        try {
            T t = (T) Class.forName(clazz.getName()).newInstance();
            BeanUtils.copyProperties(obj, t, ignoreProperties);
            return t;
        } catch (Exception e) {
            log.error("objToBeanVo error:" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

}